# -*- coding: utf-8 -*-
# @author : wanglei
# @date : 2020/5/7 19:59
# @description : 向量
from manimlib.imports import *
from from_victor.imports import *

"""
向量的表示方式：代数表示、几何表示、坐标表示、矩阵表示
"""
class VectorExpression(GraphScene):
    CONFIG = {
        "x_min": 0,
        "x_max": 5,  # X坐标范围
        "x_tick_frequency": 1,  # X坐标刻度密度
        "x_labeled_nums": range(0, 6, 1),  # X坐标刻度数值
        "x_axis_label": "$x$",  # X坐标标注

        "y_min": 0,
        "y_max": 4,  # Y坐标范围
        "y_tick_frequency": 1,  # Y坐标刻度密度
        "y_labeled_nums": range(0, 5, 1),  # Y坐标刻度数值
        "y_axis_label": "$y$",  # Y坐标标注
        "exclude_zero_label": True,  # 不显示Y坐标的0刻度
        "x_axis_width": 5,
        "y_axis_height": 4,
        "graph_origin": 2*LEFT + DOWN
    }
    captions = [
        '向量是具有方向和大小的量'
        '方向可以指代身高、体重等有实际意义的特征',
        '向量有四种表示方法',
        '第一种是代数表示，字母上面带一个箭头，小写字母代表线段，大写字母代表向量的起始点',
        '第二种是几何表示，用带有方向的箭头表示',
        '第三种是坐标表示，用终点坐标来表示',
        '第四种是矩阵表示，就是将终点的坐标形式换成矩阵形式',
        '向量的矩阵表示，会方便对实际问题建模',
    ]
    def construct(self):
        vector_text = TextMobject('向量是具有方向和大小的量', tex_to_color_map={'方向': DARK_BLUE, '大小': DARK_BLUE})
        self.play(FadeInFromDown(vector_text))
        self.wait(5)
        four_text = TextMobject('向量有四种表示方法')
        self.play(Transform(vector_text, four_text))
        self.wait(2)
        self.play(FadeOutAndShift(vector_text))
        # 代数表示
        title1 = TextMobject('代数表示')
        title1.move_to(5 * UP)
        line=Line(3.5 * LEFT, 3.5 * RIGHT, color = 'GOLD')
        line.next_to(title1, DOWN)
        self.play(Write(title1), Write(line))
        v1_algebra1 = TexMobject('\\overrightarrow{a}')
        v1_algebra1.move_to(UP)
        v1_algebra2 = TexMobject('\\overrightarrow{AB}')
        v1_algebra2.next_to(v1_algebra1, DOWN)
        self.play(Write(v1_algebra1))
        self.play(Write(v1_algebra2))
        self.wait(5)
        self.play(FadeOut(v1_algebra1),FadeOut(v1_algebra2))
        # 几何表示
        title2 = TextMobject('几何表示')
        title2.move_to(5 * UP)
        self.play(Transform(title1, title2))
        v1 = Arrow(start=self.graph_origin, end=UP, stroke_width=3, buff=0)
        v1.set_color(RED)
        v1.move_to(ORIGIN)
        self.play(Write(v1))
        self.wait(3)
        self.play(FadeOut(v1))
        # 坐标表示
        title3 = TextMobject('坐标表示')
        title3.move_to(5 * UP)
        self.play(Transform(title1, title3))
        self.setup()
        self.setup_axes()
        v2 = Arrow(start=self.graph_origin, end=2*UP, stroke_width=3, buff=0)
        v2.set_color(BLUE)
        v2_coordinate = TextMobject('(2, 3)', color=RED)
        self.play(Write(v2))
        self.play(Write(v2_coordinate.next_to(v2,RIGHT,aligned_edge=UP)))
        self.wait(3)
        # 矩阵表示
        title4 = TextMobject('矩阵表示')
        title4.move_to(5 * UP)
        self.play(Transform(title1, title4))
        v2_matrix = TexMobject('\\begin{bmatrix} 2 \\\ 3 \\end{bmatrix}', color=YELLOW)
        self.play(Transform(v2_coordinate, v2_matrix.next_to(v2,RIGHT,aligned_edge=UP)))
        self.wait(3)


"""
向量的运算-加法
"""
class VectorOperationAdd(GraphScene):
    CONFIG = {
        "x_min": 0,
        "x_max": 6,  # X坐标范围
        "x_tick_frequency": 1,  # X坐标刻度密度
        "x_labeled_nums": range(0, 7, 1),  # X坐标刻度数值
        "x_axis_label": "$x$",  # X坐标标注

        "y_min": 0,
        "y_max": 7,  # Y坐标范围
        "y_tick_frequency": 1,  # Y坐标刻度密度
        "y_labeled_nums": range(0, 8, 1),  # Y坐标刻度数值
        "y_axis_label": "$y$",  # Y坐标标注
        "exclude_zero_label": True,  # 不显示Y坐标的0刻度
        "x_axis_width": 6,
        "y_axis_height": 7,
        "graph_origin": 3 * LEFT + 2 * DOWN
    }
    captions = [
        '向量的加法，两个向量相加',
        '根据向量的平移不变性，将向量b移动到向量a的终点',
        '依据三角形法则，结果向量就是a的起点指向b的终点这个向量',
        '可以直接矩阵计算得到这个向量',
    ]

    def construct(self):
        self.setup()
        self.setup_axes()
        # 加
        v1 = Arrow(start=self.graph_origin, end=LEFT + UP, color=RED, stroke_width=3, buff=0)
        v1_matric = TexMobject('\\begin{bmatrix} 2 \\\ 3 \\end{bmatrix}', color = RED)
        v1_matric.next_to(v1,RIGHT,aligned_edge=UP)
        v1_algebra = TexMobject('\\vec{a}', color = RED)
        v1_algebra.next_to(v1.get_center(), UP)
        v2 = Arrow(start=self.graph_origin, end=0 * RIGHT + DOWN, color=BLUE, stroke_width=3, buff=0)
        v2_matric = TexMobject('\\begin{bmatrix} 3 \\\ 1 \\end{bmatrix}', color = BLUE)
        v2_matric.next_to(v2, RIGHT, aligned_edge=UP)
        v2_algebra = TexMobject('\\vec{b}', color=BLUE)
        v2_algebra.next_to(v2.get_center(), UP)
        self.play(Write(v1), Write(v2))
        self.play(FadeIn(v1_matric), FadeIn(v2_matric))
        self.play(FadeIn(v1_algebra), FadeIn(v2_algebra))
        v2_gp = VGroup(v2,v2_matric,v2_algebra)
        #TODO:a = v1.get_end()# [0. 2. 0.] #这个是源坐标，所以不行
        # 移动这个向量
        self.play(ApplyMethod(v2_gp.shift, v1.get_end()-self.graph_origin))
        v1_v2 =  Arrow(start=self.graph_origin, end=v2_gp[0].get_end(), color=GREEN, stroke_width=3, buff=0)
        self.play(ShowCreation(v1_v2, run_time=2))
        v1_matric_copy = v1_matric.copy()
        self.play(ApplyMethod(v1_matric_copy.move_to,2*LEFT + 4.5*UP))
        add_text = TextMobject('+')
        add_text.next_to(v1_matric_copy, RIGHT)
        self.play(Write(add_text))
        v2_matric_copy = v2_matric.copy()
        self.play(ApplyMethod(v2_matric_copy.next_to, add_text, RIGHT))
        equal_text = TextMobject('=')
        equal_text.next_to(v2_matric_copy, RIGHT)
        self.play(Write(equal_text))
        v3_matric = TexMobject('\\begin{bmatrix} 2+3 \\\ 3+1 \\end{bmatrix}', color=GREEN)
        v3_matric.next_to(equal_text, RIGHT)
        self.play(Write(v3_matric))
        v3_matric_2 = TexMobject('\\begin{bmatrix} 5 \\\ 4 \\end{bmatrix}', color=GREEN)
        v3_matric_2.next_to(v1_v2.get_end(), UP)
        self.play(TransformFromCopy(v3_matric, v3_matric_2))
        self.wait(2)


"""
向量的运算-减法【使用pr处理成倒放，然后添加上最后一幕】
"""
class VectorOperationSubtraction(GraphScene):
    CONFIG = {
        "x_min": -6,
        "x_max": 6,  # X坐标范围
        "x_tick_frequency": 1,  # X坐标刻度密度
        "x_labeled_nums": range(-6, 7, 1),  # X坐标刻度数值
        "x_axis_label": "$x$",  # X坐标标注

        "y_min": -7,
        "y_max": 7,  # Y坐标范围
        "y_tick_frequency": 1,  # Y坐标刻度密度
        "y_labeled_nums": range(-7, 8, 1),  # Y坐标刻度数值
        "y_axis_label": "$y$",  # Y坐标标注
        "exclude_zero_label": True,  # 不显示Y坐标的0刻度
        "x_axis_width": 12,
        "y_axis_height": 14,
        "graph_origin": 3 * LEFT + 2 * DOWN
    }
    captions = [
        '向量的减法，两个向量相减，等于什么呢？',
        '减法可以转换为向量的加法',
        'a向量减b向量，就等于a向量加上b向量的取反',
        '我们通过矩阵直接可以进行计算',
    ]

    def construct(self):
        self.setup()
        self.setup_axes()
        v1 = Arrow(start=self.graph_origin, end=LEFT + UP, color=RED, stroke_width=3, buff=0)
        v1_matric = TexMobject('\\begin{bmatrix} 2 \\\ 3 \\end{bmatrix}', color=RED)
        v1_matric.next_to(v1, RIGHT, aligned_edge=UP)
        v1_algebra = TexMobject('\\vec{a}', color=RED)
        v1_algebra.next_to(v1.get_center(), UP)
        v2 = Arrow(start=self.graph_origin, end=0 * RIGHT + DOWN, color=BLUE, stroke_width=3, buff=0)
        v2_matric = TexMobject('\\begin{bmatrix} 3 \\\ 1 \\end{bmatrix}', color=BLUE)
        v2_matric.next_to(v2, RIGHT, aligned_edge=UP)
        v2_algebra = TexMobject('\\vec{b}', color=BLUE)
        v2_algebra.next_to(v2.get_center(), UP)
        self.play(Write(v1), Write(v2))
        self.play(FadeIn(v1_matric), FadeIn(v2_matric))
        self.play(FadeIn(v1_algebra), FadeIn(v2_algebra))
        sub_tex = TexMobject('\\vec{a}-\\vec{b}=', tex_to_color_map={'\\vec{a}': RED, '\\vec{b}':BLUE})
        sub_tex.move_to(LEFT + 3*UP)
        self.play(Write(sub_tex))
        what_text = TextMobject('?', color = GREEN).scale(1.5)
        what_text.next_to(sub_tex, RIGHT)
        self.play(Write(what_text))
        self.play(ShowCreationThenFadeAround(what_text))
        self.wait(2)
        add_tex = TexMobject('\\vec{a}+(-\\vec{b})', tex_to_color_map={'\\vec{a}': RED, '\\vec{b}': BLUE})
        add_tex.next_to(sub_tex, RIGHT)
        self.play(Transform(what_text, add_tex))
        self.wait(2)
        sa_gp = VGroup(sub_tex, add_tex, what_text)
        self.play(FadeOut(sa_gp))
        all_mobjects = VGroup(*(self.get_mobjects()))
        self.play(ApplyMethod(all_mobjects.move_to, ORIGIN))
        v2_2 = Arrow(start=v1.get_start(), end=3*LEFT + DOWN, color=BLUE, stroke_width=3, buff=0)
        v2_matric_2 = TexMobject('\\begin{bmatrix} -3 \\\ -1 \\end{bmatrix}', color=BLUE)
        v2_matric_2.next_to(v2_2.get_end(), DOWN, aligned_edge=RIGHT)
        v2_algebra_2 = TexMobject('\\vec{-b}', color=BLUE)
        v2_algebra_2.next_to(v2_2.get_center(), DOWN)
        v2_2_gp = VGroup(v2_2, v2_matric_2, v2_algebra_2)
        v2_gp = VGroup(v2, v2_matric, v2_algebra)
        self.play(Transform(v2_gp, v2_2_gp))
        self.wait(2)
        self.remove(v2_gp)
        self.play(ApplyMethod(v2_2_gp.shift, v1.get_end()-(v1.get_start()+ORIGIN)))
        self.play(ApplyMethod(v2_matric_2.next_to, v2_2.get_end(), UP, buff=LARGE_BUFF))
        self.play(ApplyMethod(v2_algebra_2.next_to, v2_2.get_center(),UP))

        v3 = Arrow(start=v1.get_start(), end=v2_2.get_end(), color=GREEN, stroke_width=3, buff=0)
        self.play(ShowCreation(v3, run_time=2))
        v3_matric =  TexMobject('\\begin{bmatrix} 2+(-3) \\\ 3+(-1) \\end{bmatrix}', color=GREEN)
        v3_matric.next_to(v3.get_center(),2*LEFT)
        self.play(FadeIn(v3_matric))
        self.wait(1)
        v3_matric_2 = TexMobject('\\begin{bmatrix} -1 \\\ 2 \\end{bmatrix}', color=GREEN)
        v3_matric_2.next_to(v3.get_center(), 2 * LEFT)
        self.play(Transform(v3_matric, v3_matric_2))
        self.wait(2)

"""
向量的运算-减法最后一幕
"""
class VectorOperationSubtraction2(GraphScene):
    CONFIG = {
        "x_min": -6,
        "x_max": 6,  # X坐标范围
        "x_tick_frequency": 1,  # X坐标刻度密度
        "x_labeled_nums": range(-6, 7, 1),  # X坐标刻度数值
        "x_axis_label": "$x$",  # X坐标标注

        "y_min": -7,
        "y_max": 7,  # Y坐标范围
        "y_tick_frequency": 1,  # Y坐标刻度密度
        "y_labeled_nums": range(-7, 8, 1),  # Y坐标刻度数值
        "y_axis_label": "$y$",  # Y坐标标注
        "exclude_zero_label": True,  # 不显示Y坐标的0刻度
        "x_axis_width": 12,
        "y_axis_height": 14,
        "graph_origin": 3 * LEFT + 2 * DOWN
    }

    def construct(self):
        self.setup()
        self.setup_axes()
        v1 = Arrow(start=self.graph_origin, end=LEFT + UP, color=RED, stroke_width=3, buff=0)
        v1_matric = TexMobject('\\begin{bmatrix} 2 \\\ 3 \\end{bmatrix}', color=RED)
        v1_matric.next_to(v1, RIGHT, aligned_edge=UP)
        v1_algebra = TexMobject('\\vec{a}', color=RED)
        v1_algebra.next_to(v1.get_center(), UP)
        v2 = Arrow(start=self.graph_origin, end=0 * RIGHT + DOWN, color=BLUE, stroke_width=3, buff=0)
        v2_matric = TexMobject('\\begin{bmatrix} 3 \\\ 1 \\end{bmatrix}', color=BLUE)
        v2_matric.next_to(v2, RIGHT, aligned_edge=UP)
        v2_algebra = TexMobject('\\vec{b}', color=BLUE)
        v2_algebra.next_to(v2.get_center(), UP)

        sub_tex = TexMobject('\\vec{a}-\\vec{b}=', tex_to_color_map={'\\vec{a}': RED, '\\vec{b}':BLUE})
        sub_tex.move_to(LEFT + 3*UP)
        gp = VGroup(v1, v2, v1_matric, v2_matric, v1_algebra, v2_algebra, sub_tex)
        self.add(gp)
        self.wait(2)
        v3 = Arrow(start=v2.get_end(), end=v1.get_end(), color=GREEN, stroke_width=3, buff=0)
        v3_algebra = TexMobject('\\vec{c}', color = GREEN)
        v3_algebra.next_to(v3.get_center(), RIGHT)
        self.play(ShowCreation(v3), Write(v3_algebra))
        self.play(ApplyMethod(v3_algebra.copy().next_to, sub_tex, RIGHT))
        self.wait(2)

"""
向量的运算-点积
"""
class VectorOperationDotProduct(GraphScene):
    CONFIG = {
        "x_min": 0,
        "x_max": 6,  # X坐标范围
        "x_tick_frequency": 1,  # X坐标刻度密度
        "x_labeled_nums": range(0, 7, 1),  # X坐标刻度数值
        "x_axis_label": "$x$",  # X坐标标注

        "y_min": 0,
        "y_max": 7,  # Y坐标范围
        "y_tick_frequency": 1,  # Y坐标刻度密度
        "y_labeled_nums": range(0, 8, 1),  # Y坐标刻度数值
        "y_axis_label": "$y$",  # Y坐标标注
        "exclude_zero_label": True,  # 不显示Y坐标的0刻度
        "x_axis_width": 6,
        "y_axis_height": 7,
        "graph_origin": ORIGIN,
        "camera_config": {"frame_center": -(3 * LEFT + 2 * DOWN)},
    }
    captions = [
        '两个向量的点积',
        '根据它的定义，就是两个向量的模相乘后，再乘以这两个向量夹角的cos值',
        '而向量b的模乘以cos theta就是向量b在向量a上的投影长度'
        '使用矩阵计算该值，等于a矩阵的转置乘以b矩阵',
    ]

    def construct(self):
        self.setup()
        self.setup_axes()
        self.x_label.next_to(self.x_axis.get_corner(UP + RIGHT), RIGHT,buff=0)
        self.y_label.next_to(self.y_axis.get_corner(UP + RIGHT), 2*UP,buff=0)
        # 点积
        v1 = Arrow(start=self.graph_origin, end=2*RIGHT + 3*UP, color=RED, stroke_width=3, buff=0)
        v1_matric = TexMobject('\\begin{bmatrix} 2 \\\ 3 \\end{bmatrix}', color=RED)
        v1_matric.next_to(v1, RIGHT, aligned_edge=UP)
        v1_algebra = TexMobject('\\vec{a}', color=RED)
        v1_algebra.next_to(v1.get_center(), UP)
        v2 = Arrow(start=self.graph_origin, end=3 * RIGHT + UP, color=BLUE, stroke_width=3, buff=0)
        v2_matric = TexMobject('\\begin{bmatrix} 3 \\\ 1 \\end{bmatrix}', color=BLUE)
        v2_matric.next_to(v2, RIGHT, aligned_edge=UP)
        v2_algebra = TexMobject('\\vec{b}', color=BLUE)
        v2_algebra.next_to(v2.get_center(), UP)

        # 夹角
        self.play(Write(v1), Write(v2))
        self.play(FadeIn(v1_matric), FadeIn(v2_matric))
        self.play(FadeIn(v1_algebra), FadeIn(v2_algebra))
        start_angle, angle = get_arc_angle(v2, v1)
        arc = Arc(start_angle, angle=angle, radius=0.5, stroke_width=2)
        self.play(Write(arc))
        theta = TexMobject('\\theta')
        theta.next_to(arc, UR, buff=0)
        self.play(Write(theta))
        tex1 = TexMobject('\\vec{a}.\\vec{b}=|\\vec{a}||\\vec{b}|\\cos\\theta',
                          tex_to_color_map={'\\vec{a}': RED, '\\vec{b}':BLUE})
        tex1.shift(2.5*RIGHT+6*UP)
        self.play(Write(tex1))
        self.wait(2)

        # 标记投影计算位置
        projected_tex = tex1[6:].copy()
        self.play(ShowCreationThenFadeAround(projected_tex))

        # 做垂线
        projected_point = get_projected_point(v2, v1)
        dashed_line = DashedLine(v2.get_end(), projected_point, color = YELLOW)
        self.play(ShowCreation(dashed_line))

        # 直角
        p0, p1, p2, p3 = get_right_angle(v1.get_center(), dashed_line.get_end(), dashed_line.get_center(), 0.3)
        line1 = Line(p1, p2)
        line2 = Line(p2, p3)
        self.play(ShowCreation(line1), ShowCreation(line2))

        # 标出投影长度
        line = Line(ORIGIN, projected_point)
        brace = Brace(line, line.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=BLUE)
        self.play(ShowCreation(brace))
        self.wait(2)

        # 点积【等于a矩阵的转置，乘以b矩阵】
        tex2 = TexMobject(
            '\\begin{bmatrix} 2 & 3 \\end{bmatrix} . \\begin{bmatrix} 3 \\\ 1 \\end{bmatrix} = 2*3 + 3*1 = 9',
            tex_to_color_map={'\\begin{bmatrix} 2 & 3 \\end{bmatrix}': RED,
                              '\\begin{bmatrix} 3 \\\ 1 \\end{bmatrix}': BLUE}).scale(0.9)
        tex2.next_to(tex1, DOWN, aligned_edge=LEFT)
        self.play(Write(tex2))
        self.wait(2)

"""
向量的运算-乘法（叉乘）
"""
class VectorOperationProduct(GraphScene):
    CONFIG = {
        "x_min": 0,
        "x_max": 6,  # X坐标范围
        "x_tick_frequency": 1,  # X坐标刻度密度
        "x_labeled_nums": range(0, 7, 1),  # X坐标刻度数值
        "x_axis_label": "$x$",  # X坐标标注

        "y_min": 0,
        "y_max": 7,  # Y坐标范围
        "y_tick_frequency": 1,  # Y坐标刻度密度
        "y_labeled_nums": range(0, 8, 1),  # Y坐标刻度数值
        "y_axis_label": "$y$",  # Y坐标标注
        "exclude_zero_label": True,  # 不显示Y坐标的0刻度
        "x_axis_width": 6,
        "y_axis_height": 7,
        "graph_origin": ORIGIN,
        "camera_config": {"frame_center": -(3 * LEFT + 2 * DOWN)},
    }
    captions = [
        '两个向量的叉乘',
        '根据它的定义，就是两个向量的模相乘后，再乘以这两个向量夹角的sin值',
        '向量a的模就是它的长度，而向量b的模乘以sin theta就是从向量b的终点，朝 向量a做垂线的长度'
        '那其实该值就是底乘以高，也就是平行四边形的面积',
        '但特殊的就是这个面积是有方向的，从而叉乘的结果就是带有方向的面积',
        '该方向垂直于a、b组成的向量空间，符合右手定则',
    ]

    def construct(self):
        self.setup()
        self.setup_axes()
        self.x_label.next_to(self.x_axis.get_corner(UP + RIGHT), RIGHT,buff=0)
        self.y_label.next_to(self.y_axis.get_corner(UP + RIGHT), 2*UP,buff=0)
        # 点积
        v1 = Arrow(start=self.graph_origin, end=2*RIGHT + 3*UP, color=RED, stroke_width=3, buff=0)
        v1_matric = TexMobject('\\begin{bmatrix} 2 \\\ 3 \\end{bmatrix}', color=RED)
        v1_matric.next_to(v1, RIGHT, aligned_edge=UP)
        v1_algebra = TexMobject('\\vec{a}', color=RED)
        v1_algebra.next_to(v1.get_center(), UP)
        v2 = Arrow(start=self.graph_origin, end=3 * RIGHT + UP, color=BLUE, stroke_width=3, buff=0)
        v2_matric = TexMobject('\\begin{bmatrix} 3 \\\ 1 \\end{bmatrix}', color=BLUE)
        v2_matric.next_to(v2, RIGHT, aligned_edge=UP)
        v2_algebra = TexMobject('\\vec{b}', color=BLUE)
        v2_algebra.next_to(v2.get_center(), UP)

        # 夹角
        self.play(Write(v1), Write(v2), FadeIn(v1_matric), FadeIn(v2_matric), FadeIn(v1_algebra), FadeIn(v2_algebra))
        start_angle, angle = get_arc_angle(v2, v1)
        arc = Arc(start_angle, angle=angle, radius=0.5, stroke_width=2)
        self.play(Write(arc))
        theta = TexMobject('\\theta')
        theta.next_to(arc, UR, buff=0)
        self.play(Write(theta))
        tex1 = TexMobject('\\vec{a} \\times \\vec{b} =',
                          '| \\vec{a}|',
                          '|\\vec{b}|\\sin\\theta',
                          tex_to_color_map={'\\vec{a}': RED, '\\vec{b}':BLUE})
        tex1.shift(2.5*RIGHT+6*UP)
        self.play(Write(tex1), run_time=3)
        self.wait()

        # 底
        bottom = tex1[4:7].copy()
        self.play(ShowCreationThenFadeAround(bottom), run_time=2)
        # 标出底的长度
        line = Line(ORIGIN, v1.get_end())
        bottom_brace = Brace(line, line.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=RED)
        self.play(ShowCreationThenFadeOut(bottom_brace), run_time=2)
        self.wait(2)

        # 高
        height = tex1[7:].copy()
        self.play(ShowCreationThenFadeAround(height), run_time=2)

        # 做垂线
        projected_point = get_projected_point(v2, v1)
        dashed_line = DashedLine(v2.get_end(), projected_point, color=YELLOW)
        self.play(ShowCreation(dashed_line))

        # 直角
        p0, p1, p2, p3 = get_right_angle(v1.get_center(), dashed_line.get_end(), dashed_line.get_center(), 0.3)
        line1 = Line(p1, p2)
        line2 = Line(p2, p3)
        self.play(ShowCreation(line1), ShowCreation(line2))
        self.wait()

        # 标出高的长度
        line = Line(v2.get_end(), projected_point)
        height_brace = Brace(line, line.get_angle(), is_fit_UP=True, buff=SMALL_BUFF, color=YELLOW)
        self.play(ShowCreationThenFadeOut(height_brace), run_time=2)

        # 移动向量
        v2_copy = v2.copy()
        v1_copy = v1.copy()
        self.play(ApplyMethod(v2_copy.shift, v1.get_end() - self.graph_origin), ApplyMethod(v1_copy.shift, v2.get_end() - self.graph_origin))

        # 面积
        area = Polygon(ORIGIN,
                       v1.get_end(),
                       [5, 4, 0],
                       v2.get_end(),
                       is_closed=True,
                       stroke_opacity=0.4,
                       fill_color=GRAY,
                       fill_opacity=0.6)
        self.play(Write(area))
        self.play(ApplyWave(area))
        self.wait(3)
        # 带方向的面积
        value_text = TextMobject('带方向的面积').scale(0.9)
        value_text.next_to(tex1[3], RIGHT)
        self.play(Transform(tex1[4:], value_text))
        self.wait()










"""
class ShowCrossProductFormula(Scene):
    def construct(self):
        colors = [X_COLOR, Y_COLOR, Z_COLOR]

        arrays = [
            ["%s_%d" % (s, i) for i in range(1, 4)]
            for s in ("v", "w")
        ]
        matrices = list(map(Matrix, arrays))
        for matrix in matrices:
            for entry, color in zip(matrix.get_entries(), colors):
                entry.set_color(color)
        m1, m2 = matrices
        cross_product = VGroup(m1, TexMobject("\\times"), m2)
        cross_product.arrange()
        cross_product.shift(2 * LEFT)

        entry_dicts = [{} for x in range(3)]
        movement_sets = []
        for a, b, c in it.permutations(list(range(3))):
            sign = self.get_perm_sign(a, b, c)
            e1, e2 = m1.get_entries()[b], m2.get_entries()[c]
            for e in e1, e2:
                e.target = e.copy()
            dot = TexMobject("\\cdot")
            syms = VGroup(dot)

            if sign < 0:
                minus = TexMobject("-")
                syms.add(minus)
                cross_entry = VGroup(minus, e2.target, dot, e1.target)
                cross_entry.arrange()
                entry_dicts[a]["negative"] = cross_entry
            else:
                cross_entry = VGroup(e1.target, dot, e2.target)
                cross_entry.arrange()
                entry_dicts[a]["positive"] = cross_entry
            cross_entry.arrange()
            movement_sets.append([
                e1, e1.target,
                e2, e2.target,
                syms
            ])

        result = Matrix([
            VGroup(
                entry_dict["positive"],
                entry_dict["negative"],
            ).arrange()
            for entry_dict in entry_dicts
        ])
        equals = TexMobject("=").next_to(cross_product)
        result.next_to(equals)

        self.play(FadeIn(cross_product))
        self.play(
            Write(equals),
            Write(result.get_brackets())
        )
        self.wait()
        movement_sets[2], movement_sets[3] = movement_sets[3], movement_sets[2]
        for e1, e1_target, e2, e2_target, syms in movement_sets:
            e1.save_state()
            e2.save_state()
            self.play(
                e1.scale_in_place, 1.5,
                e2.scale_in_place, 1.5,
            )
            self.play(
                Transform(e1.copy(), e1_target),
                Transform(e2.copy(), e2_target),
                Write(syms),
                e1.restore,
                e2.restore,
                path_arc=-np.pi / 2
            )
        self.wait()

    def get_perm_sign(self, *permutation):
        identity = np.identity(len(permutation))
        return np.linalg.det(identity[list(permutation)])
class CrossBasisVectors(LinearTransformationScene):
    def construct(self):
        self.plane.fade()
        i_label = self.get_vector_label(
            self.i_hat, "\\hat{\\imath}",
            direction = "right",
            color = X_COLOR,
        )
        j_label = self.get_vector_label(
            self.j_hat, "\\hat{\\jmath}",
            direction = "left",
            color = Y_COLOR,
        )
        for label in i_label, j_label:
            self.play(Write(label))
            label.target = label.copy()
        i_label.target.scale(1.5)
        j_label.target.scale(1.2)

        self.wait()

        times = TexMobject("\\times")
        cross = VGroup(i_label.target, times, j_label.target)
        cross.arrange()
        cross.next_to(ORIGIN).shift(1.5*UP)
        cross_rect = BackgroundRectangle(cross)
        eq = TexMobject("= + 1")
        eq.add_background_rectangle()
        eq.next_to(cross, RIGHT)

        self.play(
            ShowCreation(cross_rect),
            MoveToTarget(i_label.copy()),
            MoveToTarget(j_label.copy()),
            Write(times),
        )
        self.play(Write(eq))
        self.wait()
        arc = self.get_arc(self.i_hat, self.j_hat, radius = 1)
        # arc.set_color(GREEN)
        self.play(ShowCreation(arc))
        self.wait()

    def get_arc(self, v, w, radius=2):
        v_angle, w_angle = v.get_angle(), w.get_angle()
        nudge = 0.05
        arc = Arc(
            # (1 - 2 * nudge) * (w_angle - v_angle),
            start_angle=interpolate(v_angle, w_angle, nudge),
            radius=radius,
            stroke_width=8,
        )
        arc.add_tip()
        return arc

class Test(Scene):
    CONFIG = {
        # "camera_config": {"frame_center": -(3 * LEFT + 2 * DOWN)}
    }
    def construct(self):
        test = TextMobject('test')
        test.move_to(ORIGIN)
        line = Line(ORIGIN, UR)
        self.play(Write(line))
        brace = Brace(line, UP, buff=SMALL_BUFF)
        self.play(Write(brace))

class ThreeDSpace(ThreeDScene):
    def construct(self):
        axes = ThreeDAxes()
        self.add(axes)
        self.set_camera_orientation(phi=70 * DEGREES, theta=-130 * DEGREES)
        self.begin_ambient_camera_rotation()

        density = 1 # 密度
        radius = 3 # 半径
        lines = VGroup(*[
            VGroup(*[
                Line(
                    radius * IN, radius * OUT,
                    stroke_color=WHITE,
                    stroke_width=1,
                    stroke_opacity=0.5,
                ).shift(x * RIGHT + y * UP)
                for x in np.arange(-radius, radius + density, density)
                for y in np.arange(-radius, radius + density, density)
            ]).rotate(n * 120 * DEGREES, axis=[1, 1, 1])
            for n in range(3)
        ])

        self.play(Write(lines))
        self.wait(30)
"""